/*
 * author: VDaras
 */

#include "Screen.h"
#include "SDLException.h"
#include <assert.h>
#include <GL/gl.h>
#include <vector>

namespace sdl
{

/*
 * Constructor initializes screen. If initilization fails then an Exception is
 * thrown and the application must exit, since it's a critical error
 *
 * @param
 * screenW: screen width
 * screenH: screen height
 * bpp: bits per pixel aka screen depth
 * fullscreen: boolean value indicating if the application runs on fullscreen mode
 */

Screen::Screen(int screenW, int screenH, int bpp, bool fullscreen, bool opengl)
:
m_isFullscreen(fullscreen),
m_openGL(opengl)
{ //try setting up the screen
    if( !init( screenW, screenH, bpp, fullscreen, opengl ) )
    {
        //if unsuccessful , indicate failure
        throw Exception( SDL_GetError( ) );
    }
}

Screen::~Screen()
{
}

/*
 * Flips and updates screen. Returns false if an error
 * occurs.
 */

bool Screen::Flip()
{
    if( m_openGL )
    {
        SDL_GL_SwapBuffers( );
        return true;
    }
    else
    {
        SDL_Surface *buff = GetBuffer( );

        //make sure the screen's surface is valid
        assert( buff != NULL );

        //update screen, check operation's status
        if( SDL_Flip( buff ) == -1 )
        {
            //if error code is failure, indicate failure
            return false;
        }

        //indicate success
        return true;
    }
}

/**
 * Clears the screen to black color.
 */

void Screen::Clear()
{
    if( m_openGL )
    {
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    }
    else
    {
        SDL_Surface *buff = GetBuffer( );

        //make sure that the screen's surface is valid
        assert( buff != NULL );

        //fill the screen using black color
        SDL_Rect rect = { 0, 0, GetWidth( ), GetHeight( ) };
        SDL_FillRect( GetBuffer( ), &rect, 0 );
    }
}

/**
 * Initializes screen, returns false if failed.
 *
 * @param
 * - screenW: screen width
 * - screenH: screen height
 * - bpp: bits per pixel aka pixel depth
 * - fullscreen: boolean value indicating if the application runs on fullscreen mode
 */

bool Screen::init(int screenW, int screenH, int bpp, bool fullscreen, bool opengl)
{
    //create a temporary primitive surface
    SDL_Surface *screen = NULL;

    //if we need a fullscreen application
    if( fullscreen )
    {
        //setup a fullscreen doublebuffered surface
        if( opengl )
            screen = SDL_SetVideoMode( screenW, screenH, bpp, SDL_HWSURFACE | SDL_FULLSCREEN | SDL_OPENGL );
        else
            screen = SDL_SetVideoMode( screenW, screenH, bpp, SDL_HWSURFACE | SDL_FULLSCREEN | SDL_DOUBLEBUF );
    }
    else //if not
    {
        //setup a windowed surface
        if( opengl )
            screen = SDL_SetVideoMode( screenW, screenH, bpp, SDL_OPENGL );
        else
            screen = SDL_SetVideoMode( screenW, screenH, bpp, SDL_HWSURFACE );

    }

    //if setting up the screen was successful
    if( screen )
    {
        //set up the current buffer to the new screen
        SetBuffer( screen );
        //indicate success
        return true;
    }

    //setting up screen failed, indicate failure
    return false;
}

};